#!/usr/bin/perl
use strict;

my $prefix = shift;
my $PREFIX = uc $prefix;
my $include= shift || "GL/$prefix.h";

my $type = "";
my $enum = "";
my $func = "";
my $undef_type = "";
my $undef_enum = "";
my $undef_func = "";
while (<>) {
	/typedef .*\b$PREFIX([a-z][a-zA-Z0-9]*[a-z0-9])\b;/ and do {
		my $orig = "$PREFIX$1";
		my $name = &escape(&uncamel($1)) . "_t";
		$orig = sprintf("%-20s", $orig);
		$name = sprintf("\%+20s", $name);
		$type .= "\tFORWARD_TYPE($name, $orig);\n";
		$undef_type .= "#define $orig static_assert(false, \"no such type\");\n";
		next;
	};

	/#define\s+\b${PREFIX}_([A-Z0-9_]+)\b/ and do {
		my $orig = "${PREFIX}_$1";
		my $name = "_" . &escape(lc $1);
		$undef_enum .= "#undef $orig\n";
		$orig = sprintf("%-36s", $orig);
		$name = sprintf("%-36s", $name);
		$enum .= "\tFORWARD_ENUM($name, $orig);\n";
		next;
	};

	/\b$prefix([A-Z][a-z][A-Za-z0-9]*)\b\s*\(/ and do {
		my $orig = "$prefix$1";
		my $name = &escape(&uncamel($1));
		my $uorig = sprintf("%-28s", "$orig(...)");
		$orig = sprintf("%-28s", $orig);
		$name = sprintf("%-28s", $name);
		$func .= "\tFORWARD_FUNC($name, $orig);\n";
		$undef_func .= "#define $uorig static_assert(false, \"no such function\");\n";
		next;
	};
}

print <<END;
#pragma once
#include <$include>

namespace $prefix
{
#define FORWARD_TYPE(NAME, VAL)		using NAME = ::VAL
#define FORWARD_ENUM(NAME, VAL)		constexpr auto NAME = VAL
#define FORWARD_FUNC(NAME, VAL)		template <class ...ARGS> inline auto NAME (ARGS... args) { return VAL (args...); }

	// type
$type
	// enum
$enum
	// function
$func
#undef FORWARD_TYPE
#undef FORWARD_ENUM
#undef FORWARD_FUNC
}


// undef type
$undef_type
// undef enum
$undef_enum
// undef function
$undef_func
END

sub uncamel
{
	my $name = shift;
	$name =~ s/[0-9]?[A-Z]+/'_' . lc$&/xeg;
	$name =~ s/[A-Z]/'_' . lc$&/xeg;
	$name =~ s/^_//;
	$name;
}
sub escape
{
	my $name = shift;
	$name =~ s/^[0-9]/_$&/g;
	$name;
}

